package com.yanqu.road.server.gameplayer.module.activity.cat.action;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.entity.activity.cat.*;
import com.yanqu.road.entity.activity.cat.config.CatMissionInfo;
import com.yanqu.road.server.gameplayer.module.activity.cat.CatActivityConfig;
import com.yanqu.road.server.gameplayer.module.activity.cat.ConnectResult;
import com.yanqu.road.server.manger.activity.cat.CatMgr;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

public abstract class BaseElementAction {

    public static Map<Integer, BaseElementAction> actionMap = new HashMap<>();

    public static Map<Integer, BaseElementAction> getActionMap() {
        return actionMap;
    }

    public static final int allElementCount = CatActivityConfig.ROW_NUM * CatActivityConfig.COLUMN_NUM;

    public BaseElementAction(int type) {
        this.type = type;
    }

    private final int type;

    public int getType() {
        return type;
    }

    public static BaseElementAction getByType(int type){
        return getActionMap().get(type);
    }

    /**
     * 连线是否可到达
     */
    public boolean acceptNext(ConnectResult context){
        if(context.getRet() != 0){
            return false;
        }
        int maxIndex =  context.getPositionList().size() - 1;
        Element start = getStartElement(context, maxIndex);
        Element next = getNextElement(context, maxIndex);
        if(start != null && next != null){
            //判断两者的一定要是相邻的
            if(Math.abs(start.getX() - next.getX()) > 1 || Math.abs(start.getY() - next.getY()) > 1){
                context.setRet(-1);
                return false;
            }
            if(this.type == start.getType()) {
                accept(start, next, context);
            }else {
                BaseElementAction action = getByType(start.getType());
                action.accept(start, next, context);
            }
        }
        if(context.getIndex() == maxIndex){
            context.setIndex(-1);
        }
        return context.getRet() == 0;
    }

    /**
     * 下一个连线元素
     */
    public Element getNextElement(ConnectResult context, int maxIndex) {
        Element next = null;
        if(context.getIndex() + 1 <= maxIndex){
            Position position = context.getPositionList().get(context.getIndex() + 1);
            context.setIndex(context.getIndex() + 1);
            next = CatMgr.getElement(context.getElements(), position.getX(), position.getY());
        }
        return next;
    }

    /**
     * 起始连线元素（主角）
     */
    public Element getStartElement(ConnectResult context, int maxIndex) {
        Element start = null;
        if(context.getIndex() == -1){
            start = CatMgr.getElement(context.getElements(), context.getRolePosition().getX(), context.getRolePosition().getY());
        }else {
            if(context.getIndex() <= maxIndex) {
                Position position = context.getPositionList().get(context.getIndex());
                start = CatMgr.getElement(context.getElements(), position.getX(), position.getY());
            }
        }
        return start;
    }

    /**
     * 连线
     */
    public void connectNext(ConnectResult context){
        if(context.getRet() != 0){
            return;
        }
        int maxIndex =  context.getPositionList().size() -1;
        Element next = getNextElement(context, maxIndex);
        if(next != null){
            //缓存
            context.getDisappearList().add(next.clone());
            if(this.type == next.getType()) {
                connect(next, context);
            }else {
                BaseElementAction action = getByType(next.getType());
                action.connect(next, context);
            }
        }
        if(context.getIndex() == maxIndex){
            context.setIndex(-1);

            //主角位置变化
            Element role = context.getElements()[context.getRolePosition().getX()][context.getRolePosition().getY()];
            int val = role.getVal();
            CatMgr.clearElementTypeInfo(role);

            //CatMgr.getLogger().info("--------- role old place {}, type {}, x {}, y {}", JSONObject.toJSONString(role.getAttrs()), role.getType(), role.getX(), role.getY());

            //设置最后一个位置，为主角，保留属性，比如电车、香囊
            Position last = context.getRoleLastPosition();
            Element lastElement = context.getElements()[last.getX()][last.getY()];
            context.getRolePosition().setX(last.getX());
            context.getRolePosition().setY(last.getY());
            CatMgr.clearElementTypeInfo(lastElement);
            lastElement.setType(eElementTypes.Role.getType());
            lastElement.setVal(val);
            //CatMgr.getLogger().info("--------- role new place {}, type {}, x {}, y {}", JSONObject.toJSONString(lastElement.getAttrs()), lastElement.getType(), lastElement.getX(), lastElement.getY());

            context.getGameData().setRoleX(last.getX());
            context.getGameData().setRoleY(last.getY());

            int magnum = 1;
            CatActivityConfig config = CatMgr.getConfig();
            if(config != null){
                magnum = config.getMagnum(context.getAttackPoint());
            }
            //防止死循环
            int loop = 100;
            //万能格子生成
            List<Integer> indexList = CatMgr.getRandomPositionByWeight(CatMgr.getConfig());
            while (magnum > 0 && indexList.size() > 0){
                loop--;
                if(loop <= 0){
                    break;
                }
                int index = indexList.remove(0);
                Position position = CatMgr.coordinate(index);
                Element target = CatMgr.getElement(context.getElements(), position.getX(), position.getY());
                if(target.getType() == eElementTypes.Null.getType()){
                    continue;
                }
                if(target.getType() == eElementTypes.NotNull.getType() && target.getAttrs().size() == 0){
                    Element temp = new Element(position.getX(), position.getY());
                    temp.setType(eElementTypes.Omnipotent.getType());
                    context.getElements()[position.getX()][position.getY()] = temp;
                    context.getWanNengList().add(index);
                    magnum--;
                    continue;
                }
//                    if(target.getType() == eElementTypes.Monster.getType()){
//                        //小怪，还有血，查找下一个元素
//                        if(target.getVal() > 1){
//                            target.setVal(target.getVal() -1);
//                            context.getWanNengList().add(index);
//                            continue;
//                        }
//                    }
                //砸中达摩
                if(target.getType() == eElementTypes.Dharma.getType()){
                    if(CatMgr.hasAttr(target, eElementAttrTypes.SpiceBox.getType()) != null ||
                            CatMgr.hasAttr(target, eElementAttrTypes.Tram.getType()) != null){
                        continue;
                    }
                    Element temp = new Element(position.getX(), position.getY());
                    temp.setType(eElementTypes.Omnipotent.getType());
                    context.getElements()[position.getX()][position.getY()] = temp;
                    context.getWanNengList().add(index);
                    magnum--;
                }
            }
        }
    }

    //------------------------------------------------------------------------

    /**
     * 状态变化
     */
    public void changeNext(ConnectResult context){
        if(context.getRet() != 0){
            return;
        }
        Element next = getPreElement(context);
        if(next != null){
            if(this.type == next.getType()) {
                change(next, context);
            }else {
                BaseElementAction action = getByType(next.getType());
                action.change(next, context);
            }
        }
        if(context.getAllIndex() == 0){
            //重置下一个循环的起始位置[46->0]
            context.setAllIndex(allElementCount);
            context.getChangedList().clear();
        }
    }

    public void attackNext(ConnectResult context){
        if(context.getRet() != 0){
            return;
        }
        Element next = getPreElement(context);
        if(next != null){
            if(this.type == next.getType()) {
                attack(next, context);
            }else {
                BaseElementAction action = getByType(next.getType());
                action.attack(next, context);
            }
        }
        if(context.getAllIndex() == 0){
            //重置下一个循环的起始位置[0->46]
            context.setAllIndex(-1);

            //boss 生成小怪
            if(context.getGameData().getBossBlood() > 0){
                addMonsterElement(context);
            }
        }
    }

    /**
     * 补充小怪
     */
    private void addMonsterElement(ConnectResult context) {
        //现有小怪数量
        int monsterNum = CatMgr.elementCount(context.getElements(), eElementTypes.Monster.getType());
        CatActivityConfig config = CatMgr.getConfig();
        if(config != null){
            CatMissionInfo missionInfo = config.getCatMissionInfoById(context.getGameData().getPass());
            if(missionInfo != null && monsterNum < Integer.parseInt(missionInfo.getMonsterNumber())){
                int needNum = Integer.parseInt(missionInfo.getMonsterNumber()) - monsterNum;
                //随机位置
                List<Integer> randomIndex = CatMgr.getRandomElementIndex();
                //随机小怪
                List<Element> monsterElementList = CatMgr.randomMonsterElement(config, missionInfo, context.getGameData().isKillSilent());
                Random random = new Random();
                while (needNum > 0 && randomIndex.size() > 0 && monsterElementList.size() > 0){
                    int indexNum = randomIndex.remove(0);
                    Position position = CatMgr.coordinate(indexNum);
                    if(context.getUserData().getGameTimes() == 0 && context.getGameData().getRound() == 1){
                        if(config.getCAT_GUIDE_ANGER_POSITION().getX() == position.getX() && config.getCAT_GUIDE_ANGER_POSITION().getY() == position.getY()){
                            continue;
                        }
                    }
                    if(CatMgr.isValid(position)) {
                        //八个方向如果有小怪，就再随机
                        boolean continually = false;
                        List<Element> elementList = CatMgr.getEightDirection(context.getElements(), position);
                        for (Element element : elementList) {
                            if(element.getType() == eElementTypes.Monster.getType()){
                                continually = true;
                                break;
                            }
                        }
                        if(continually){
                            continue;
                        }
                        Element element = context.getElements()[position.getX()][position.getY()];
                        if(element != null && (element.getType() == eElementTypes.NotNull.getType() || element.getType() == eElementTypes.Dharma.getType())){
                            if(CatMgr.hasAttr(element, eElementAttrTypes.SpiceBox.getType()) != null){
                                continue;
                            }
                            if(CatMgr.hasAttr(element, eElementAttrTypes.Rail.getType()) != null && CatMgr.hasAttr(element, eElementAttrTypes.Tram.getType()) == null){
                                continue;
                            }
                            Element temp = monsterElementList.remove(0);
                            CatMgr.initMonsterElement(config, random, element, temp);
                            CatMgr.removeElementAttr(element, eElementAttrTypes.Anger.getType());
                            needNum--;
                        }
                    }
                }
            }
        }
    }

    /**
     * 盘面元素（46-0）
     */
    public Element getPreElement(ConnectResult context) {
        Element next = null;
        if(context.getAllIndex() - 1 >= 0){
            Position position = CatMgr.coordinate(context.getAllIndex() - 1);
            context.setAllIndex(context.getAllIndex() - 1);
            next = CatMgr.getElement(context.getElements(), position.getX(), position.getY());
        }
        return next;
    }

    //--------------------------------------------------------------
    /**
     * 盘面元素（0-46）
     */
    public Element getNextElement(ConnectResult context) {
        Element next = null;
        if(context.getAllIndex() + 1 < allElementCount){
            Position position = CatMgr.coordinate(context.getAllIndex() + 1);
            context.setAllIndex(context.getAllIndex() + 1);
            next = CatMgr.getElement(context.getElements(), position.getX(), position.getY());
        }
        return next;
    }

    /**
     * 生成
     */
    public void generateNext(ConnectResult context){
        if(context.getRet() != 0 || context.getGameData().getRoleBlood() <= 0){
            return;
        }
        Element next = getNextElement(context);
        if(next != null){
            if(this.type == next.getType()) {
                generate(next, context);
            }else {
                BaseElementAction action = getByType(next.getType());
                action.generate(next, context);
            }
        }
        if(context.getAllIndex() == allElementCount - 1){
            context.setAllIndex(allElementCount);

            //达摩愤怒
            //angerDharma(elements, data, config, missionInfo, tempGameData);
        }
    }

    //----------------------------------------------------------

    /**
     * 连线是否可达
     */
    abstract boolean accept(Element element, Element next, ConnectResult context);

    /**
     * 连线处理：
     * 达摩消失、监牢掉血、小怪消失（攻击boss）、
     */
    abstract void connect(Element element, ConnectResult context);

    /**
     * 地形移动
     */
    abstract void change(Element element, ConnectResult context);

    /**
     * 未消失怪物技能（攻击主角）、boss生成小怪
     */
    abstract void attack(Element element, ConnectResult context);

    /**
     * 元素掉落【元素生成】
     */
    abstract void generate(Element element, ConnectResult context);

}
